\chapter{Core}

Comme évoqué précédemment, le \textit{core} est une entité inerte comportant une série de modules.
L'axe principal de progression du développement de ces modules fut, comme demandé dans les besoins non fonctionnels, la modularité.
Ainsi, chaque module est une entité unique qui peut être éventuellement remplacée sans altérer l'intégrité des autres à partir du moment où les prototypes des fonctions qui composent ce dit module ne changent pas.

\paragraph*{}

Nous avons choisi de privilégier le style impératif dans notre implémentation.
En effet, les modules sont utilisés de manière directe. En d'autres termes, dans le cas d'une conception orientée objet, la majorité des classes qui composeraient le \textit{core} n'auraient au plus qu'une seule instance, voire même aucune dans la mesure où ces classes seraient utilisées de manière statique.
Néanmoins, la modularité de notre code permet à d'éventuels développeurs de concevoir des extensions aussi bien selon un modèle orienté objet qu'avec un modèle impératif.

\section{Commands}

Un des besoins fonctionnels essentiels du projet est l'extensibilité des commandes. En d'autres termes, il doit être possible de rajouter des commandes à SPASS de manière simple sans avoir à toucher au code du \textit{core}.
Pour ce faire, deux types de commandes ont été définis :\\

\begin{itemize}
\item Les commandes internes dites \textit{builtins}
\item Les commandes externes dites \textit{plugins}
\end{itemize}

\subsection{Builtins}

Les \textit{builtins} sont implémentées directement au sein du \textit{core}. Elles représentent un sous ensemble minimal des actions nécessaires à une administration convenable de la plateforme.
Elles utilisent toutes le module python \textit{OptParser} de manière à homogénéiser leur syntaxe d'utilisation.

\subsection{Plugins}

Les \textit{plugins} sont des commandes pouvant être rajoutées par un développeur externe.
Initialement, l'idée pour implémenter ce procédé était de s'inspirer du système de \textit{hooks} du programme \textit{Bazaar} qui permet aux développeurs de rajouter leurs propres commandes. Le principe est de charger dynamiquement tous les \textit{plugins} au démarrage du programme et d'associer un nom de commande à une classe qui contient le code de l'action.
Néanmoins, après étude du fonctionnement de ce mécanisme, nous avons choisi de ne pas le retenir.
En effet, SPASS est conçu pour pouvoir être branché sur un serveur web (\textit{django}). Une implémentation similaire à celle de \textit{Bazaar} nécessiterait de redémarrer le serveur à chaque modification de la liste des \textit{plugins}, ce qui est bien évidement très ennuyeux d'un point de vue utilisation. Pour cette raison, nous avons choisi d'effectuer une recherche du \textit{plugin} dans un sous-système de fichiers lorsque celui-ci est appelé. Cela permet en outre de pouvoir rajouter, modifier ou supprimer des \textit{plugins} à la volé sans aucune interruption de service. Nous avons tout de même tenu à comparer les performances des deux systèmes pour nous convaincre de notre choix \footnote{développé dans la section 9.1}.

\section{Base de données}

\subsection{Types manipulés par la base de données}

Les objets utilisés par le \textit{core}, à savoir :
\begin{itemize}
\item \emph{User}
\item \emph{Team}
\item \emph{TeamSet}
\item \emph{Template}
\item \emph{Assignment}
\end{itemize}
ont été déclarés de manière à fixer manuellement les n-uplets de chaque table (chaque table étant
rattachée à chaque type) pour un dialogue avec SQLAlchemy sans ambiguïté
possible. Cette méthode permet de rattacher chaque champs d'un objet à
une colonne de la table dans la base de données. Ainsi, modifier le
champs de l'objet revient à modifier la colonne correspondante dans la table.


\subsection{Couche de Dialogue SQLAlchemy}

La couche SQLAlchemy permet de faire le biais entre le \textit{core} (et ses objets) et la base
de données interne. Son API nous épargne toute syntaxe/requêtes de type
SQL, et permet de dialoguer avec un grand nombre de type de SGBD
\footnote{Système de Gestion de Base de Données}. Une grande force de SQLAlchemy réside dans le fait d'avoir la
possibilité de stocker des objets de type Python directement
dans la base de données. Ainsi, nous n'avons pas à nous pré-occuper de la
manipulation des données au sein de la base de données.

Les requêtes sur la base de données (\emph{get()}, \emph{insert()} ou
\emph{delete()}) se font alors naturellement, et ce avec n'importe quel
type de SGBD, sans avoir à connaître la syntaxe SQL.

\subsection{Pourquoi avoir choisi un modèle relationnel ?}

Le fait d'avoir choisi un SGBD relationnel (au détriment d'un modèle
orienté objet par exemple) n'est pas le fruit du
hasard. En effet, SPASS est capable de supporter une interface graphique
web au travers d'un Framework Web (écrit en Python). Celui-ci nous oblige à utiliser un modèle relationnel car il
en utilise un lui même (comme la plupart des sites web gérant des données).
Nous sommes conscients que les SGBD sont utilisés pour leur rapidité de
traitement sur un très grand nombre de données. Dans notre cas, SPASS
pourra donc gérer un grand nombre d'utilisateurs, mais en réalité ne dépassera
pas le millier d'utilisateurs.

\section{Warehouse}

Ce module est, comme son nom l'indique, dédié à la gestion de la \textit{warehouse}.
Celle-ci étant représentée par système de fichier, le module en question comporte un certains nombres de fonctions permettant d'effectuer des opérations sur ce système. Il est le seul à avoir un accès direct aux fichiers qui s'y trouvent. Toute opération (lecture ou écriture) est faite au travers de ses fonctions. Cela permet de garantir l'intégrité de la \textit{warehouse} des éventuels problèmes qui seraient dus à d'autres modules défaillants.

\section{Tests}

Les tests représentent un élément central de la plateforme. En effet, il doit être possible d'affilier des scripts de tests à un \textit{template} ou à un \textit{assignment} sans, encore, avoir à modifier de fichiers internes au \textit{core}. En outre, il est capital que les tests soient exécutés dans un environnement sécurisé pour prévenir tout dommage de la plateforme pouvant être causé, par exemple, par un \textit{assignment version} malicieux ou maladroit. De plus, l'environnement doit pouvoir être paramétrable (par exemple au niveau des variables d'environnement) pour pouvoir effectuer des tests élaborés. Enfin, la sortie des tests doit pouvoir être récupérée de manière à générer un compte rendu sur l'exécution du script.
\paragraph*{}
Pour répondre à l'ensemble de ces critères, nous avons choisis d'introduire une forme particulière pour un script de tests.
En effet, celui ci est représenté par une arborescence de fichiers. Chacun de ces fichiers représentent un test unique (écrit en python).
La retour d'un test influe sur l'ordre d'exécution des autres.
Chaque fichier de test comporte une méthode (\textit{fixture}) qui permet de définir l'environnement d'exécution du test (variables d'environnement diverses, etc...). De plus, une \textit{fixture} générale (implémentée dans le fichier éponyme) est effectuée systématiquement pour répondre aux besoins de sécurité.
Dans notre version, la \textit{fixture} générale se contente de copier les fichiers dans le répertoire \textit{/tmp} et d'effectuer les tests sur la copie de manière à préserver l'intégrité des fichiers originaux. Néanmoins, le code de ce module pourra être modifié de manière à créer un environnement plus sûr (comme un \textit{chroot} par exemple).
\paragraph*{}

Un script de tests est formalisé comme ceci :

\begin{verbatim}
|-- test_name/
|-- 1_test1.py
|-- 1_test1.d/
|   |-- 1_test3.py
|-- 2_test2.py
\end{verbatim}

\paragraph*{}
\paragraph*{}

L'algorithme d'exécution du script est le suivant :

\begin{verbatim}
Test(dir):
  Pour chaque <test> du répertoire courant:
    lancer un nouvel environnement python
    y exécuter la fixture du test puis le test lui même
    fermer l'environnement python
    écrire un fichier log contenant les sorties du test (standard et erreur)
  
    Si le test réussi et qu'il existe un dossier <test>.d:
      effectuer Test(<test>.d)
  revenir au répertoire parent
\end{verbatim}

\paragraph*{}

La gestion de l'appel des tests est similaire au mécanisme des commandes externes. En d'autres termes, il est totalement possible de rajouter des tests à la volé sans avoir à effectuer d'autres modifications.

\paragraph*{}

Ce système de tests n'est néanmoins pas conforme à notre idée première. Au départ, les scripts de tests devaient être représentés par un fichier unique qui aurait été parsé pour en extraire les informations dans des tables de la base de données interne du \textit{core}. Deux problèmes majeurs en résultaient. Premièrement, le rajout à la volée de tests devenait impossible car une synchronisation entre fichiers de tests et base de données devenait nécessaire. De plus, les scripts de tests auraient été réduits à un état très basique où seuls des appels de fonctions auraient été permis, ce qui aurait réduit considérablement les capacités du système. Nous avons donc choisi d'abandonner cette option au profit de celle développée précédemment.

\section{Message \& Error}

Ces deux modules contiennent uniquement des messages pour la sortie standard et d'erreurs du \textit{core}.
Nous avons choisis de centraliser l'ensemble des messages dans un souci d'internationalisation \footnote{développé dans la section 8.3}.

\newpage

\section{Diagramme des modules}
\begin{center}
\includegraphics[scale=0.65]{diagramme_general}
\end{center}
